#include "pwm.h"
// #include "tim.h"

TIM_HandleTypeDef htim1;

/**
 * @brief PWM 初始化
 * 
 */
void PWM_Init(void)
{
  // TIM1初始化
  TIM1_Init();
  // 启动基本定时器
  if (HAL_TIM_Base_Start(&htim1) != HAL_OK)
  {
    Error_Handler();
  }

  // 启动 TIM1 PWM 输出
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
}

void PWM_Stop(void)
{
  HAL_TIM_Base_Stop(&htim1);
  HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_ALL);
}

// 设置占空比
void PWM_Channel1(float Compare)
{
  set_pwm_param(&htim1, TIM_CHANNEL_1, Compare);
}

// 设置占空比
void PWM_Channel2(float Compare)
{
	set_pwm_param(&htim1, TIM_CHANNEL_2, Compare);
}

// 设置占空比
void PWM_Channel3(float Compare)
{
	set_pwm_param(&htim1, TIM_CHANNEL_3, Compare);
}

// 设置占空比
void set_pwm_param(TIM_HandleTypeDef *htim, uint32_t Channel, float Compare)
{
  // 确保占空比在有效范围内
  if (Compare < 0.0f)
  {
    Compare = 0.0f;
  }
  else if (Compare > (float)__HAL_TIM_GET_AUTORELOAD(htim))
  {
    Compare = (float)__HAL_TIM_GET_AUTORELOAD(htim);
  }

  __HAL_TIM_SetCompare(htim, Channel, (uint16_t)Compare);
}

/**
 * @brief 初始化TIM1定时器
 * 
 */
void TIM1_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIMEx_BreakInputConfigTypeDef sBreakInputConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  /**
   * @brief 设置TIM1实例
   * 
   */
  htim1.Instance = TIM1;                                    // 设置TIM1为定时器实例
  htim1.Init.Prescaler = 0;                                 // 预分频器值为0，不进行分频
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;  // 计数模式为中心对齐模式1
  htim1.Init.Period = 5312;                                 // 自动重装载寄存器的值，决定了PWM的周期
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;        // 时钟分频因子为2
  htim1.Init.RepetitionCounter = 0;                         // 重复计数器值为0，不进行重复计数
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // 自动重装载预装载使能

  /**
   * @brief 初始化基本定时器
   * 
   */
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置时钟源
   * 
   */
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;  // 内部时钟源
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 初始化PWM
   * 
   */
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置主从模式
   * 
   */
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF;        // 主定时器触发输出信号选择为OC4REF
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;       // 主定时器触发输出2信号选择为复位
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;// 禁用主从模式
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置断路输入
   * 
   */
  sBreakInputConfig.Source = TIM_BREAKINPUTSOURCE_BKIN;           // 断路输入源选择为BKIN
  sBreakInputConfig.Enable = TIM_BREAKINPUTSOURCE_ENABLE;         // 使能断路输入
  sBreakInputConfig.Polarity = TIM_BREAKINPUTSOURCE_POLARITY_LOW; // 断路输入极性为低电平有效
  if (HAL_TIMEx_ConfigBreakInput(&htim1, TIM_BREAKINPUT_BRK, &sBreakInputConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置PWM通道1-3
   * 
   */
  sConfigOC.OCMode = TIM_OCMODE_PWM1;               // 配置为PWM模式1
  sConfigOC.Pulse = 2655;                           // 设置脉冲宽度为2655
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;       // 输出比较极性为高电平有效
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;     // 输出比较互补极性为高电平有效
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;        // 禁用快速模式
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;    // 输出空闲状态为复位
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;  // 输出互补空闲状态为复位
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置PEM通道4
   * 
   */
  sConfigOC.OCMode = TIM_OCMODE_PWM2;
  sConfigOC.Pulse = 5311;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief 配置死区时间和断路
   * 
   */
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;       // 运行模式下的关闭状态选择为开启
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;      // 空闲模式下的关闭状态选择为开启
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;           // 锁定级别选择为关闭
  sBreakDeadTimeConfig.DeadTime = 0;                            // 死区时间设置为0
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;           // 断路状态选择为使能
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;  // 断路极性选择为高电平有效
  sBreakDeadTimeConfig.BreakFilter = 3;                         // 断路滤波器设置为3
  sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT;    // 断路AF模式选择为输入
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;        // 第二断路状态选择为禁用
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; // 第二断路极性选择为高电平有效
  sBreakDeadTimeConfig.Break2Filter = 3;                        // 第二断路滤波器设置为3
  sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;   // 第二断路AF模式选择为输入
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; // 自动输出选择为禁用
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /**
   * @brief TIM1后初始化
   * 
   */
  HAL_TIM_MspPostInit(&htim1);
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(tim_baseHandle->Instance==TIM1)
  {

    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**TIM1 GPIO Configuration
    PB12     ------> TIM1_BKIN
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  }
}

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(timHandle->Instance==TIM1)
  {
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM1 GPIO Configuration
    PA8     ------> TIM1_CH1
    PA9     ------> TIM1_CH2
    PA10     ------> TIM1_CH3
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
  if(tim_baseHandle->Instance==TIM1)
  {
    /* Peripheral clock disable */
    __HAL_RCC_TIM1_CLK_DISABLE();

    /**TIM1 GPIO Configuration
    PB12     ------> TIM1_BKIN
    PA8     ------> TIM1_CH1
    PA9     ------> TIM1_CH2
    PA10     ------> TIM1_CH3
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12);
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
  }
}
